﻿using System.Drawing;
using System.Windows.Forms;

namespace RoiControllers
{
    public class URectangle : ShapeBase
    {
        #region 字段|属性
        #region 字段
        #endregion
        #region 属性
        public float X { get => _rectangleF.X; set => _rectangleF.X = value; }
        public float Y { get => _rectangleF.Y; set => _rectangleF.Y = value; }
        public PointF Point { get => new PointF(X, Y); set => _rectangleF.Location = value; }
        public float Width { get => _rectangleF.Width; set => _rectangleF.Width = value; }
        public float Height { get => _rectangleF.Height; set => _rectangleF.Height = value; }
        #endregion
        #endregion

        #region 构造函数
        public URectangle() : base() 
        { 
            Type = ShapeType.Rectangle;
            Region = new RectangleF(0, 0, 100, 100); // 默认大小
        }
        public URectangle(float x, float y, float width, float height) : base() 
        {
            Type = ShapeType.Rectangle;
            Region = new RectangleF(x, y, width, height);
        }
        #endregion

        #region 绘制图形方法
        /// <summary> 绘制区域边缘 </summary>
        private void DrawBorder(Graphics graphics)
        {
            // 绘制矩形
            using (Pen pen = new Pen(BackColor, BorderWidth))
            {
                graphics.DrawRectangle(pen, Rectangle.Round(Region));
            }
        }
        /// <summary> 填充矩形区域 </summary>
        private void DrawRegion(Graphics graphics)
        {
            // 填充矩形
            using (SolidBrush brush = new SolidBrush(Color.FromArgb(Alpha, BackColor)))
            {
                graphics.FillRectangle(brush, Region);
            }
        }
        /// <summary>绘制所有形状手柄 </summary>
        private void DrawHandles(Graphics graphics)
        {
            RectangleF rectangle = Region;
            // 四个角的手柄
            DrawHandle(graphics, rectangle.Left, rectangle.Top);       // 左上角
            DrawHandle(graphics, rectangle.Right, rectangle.Top);      // 右上角
            DrawHandle(graphics, rectangle.Left, rectangle.Bottom);    // 左下角
            DrawHandle(graphics, rectangle.Right, rectangle.Bottom);   // 右下角
            // 计算中点位置                                                           
            float midX = rectangle.Left + rectangle.Width / 2;
            float midY = rectangle.Top + rectangle.Height / 2;
            // 四个边中点的手柄：左右上下
            DrawHandle(graphics, rectangle.Left, midY);       // 左边中点
            DrawHandle(graphics, rectangle.Right, midY);      // 右边中点
            DrawHandle(graphics, midX, rectangle.Top);          // 上边中点
            DrawHandle(graphics, midX, rectangle.Bottom);       // 下边中点
        }
        /// <summary> 绘制区域中心位置 </summary>
        private void DrawRegionCenter(Graphics graphics)
        {
            RectangleF rectangle = Region;
            // 1、计算矩形中心坐标
            float centerX = rectangle.X + rectangle.Width / 2;
            float centerY = rectangle.Y + rectangle.Height / 2;
            // 2、线长度大小（根据矩形大小自适应）
            float lineHalfLength = 3;
            // 3、绘制箭头
            using (Pen arrowPen = new Pen(BackColor, BorderWidth))
            {
                // 3.1 水平线
                PointF left = new PointF(centerX - lineHalfLength, centerY);
                PointF right = new PointF(centerX + lineHalfLength, centerY);
                graphics.DrawLine(arrowPen, left, right);
                // 3.2 垂直线
                PointF top = new PointF(centerX, centerY - lineHalfLength);
                PointF bottom = new PointF(centerX, centerY + lineHalfLength);
                graphics.DrawLine(arrowPen, top, bottom);
            }
        }
        /// <summary> 绘制形状文本描述 </summary>
        private void DrawDescription(Graphics graphics)
        {
            using (SolidBrush brush = new SolidBrush(Color.LightGreen))
            {
                Font descriptionFont = new Font("Arial", 9);
                SizeF maxTextSize = graphics.MeasureString(Description, descriptionFont);
                float x = X + Width / 2 - maxTextSize.Width / 2;
                float y = Y + Height / 2 - maxTextSize.Height;
                graphics.DrawString(Description, descriptionFont, brush, x, y);
            }
        }
        #endregion

        #region 抽象方法重写
        public override void Rotate(PointF point)
        {
            ExecuteRotateCallback();
        }
        public override void Move(PointF point)
        {
            X += point.X;
            Y += point.Y;
            LastLocation = point;
            ExecuteMoveCallback();
        }
        public override void Resize(PointF pointF)
        {
            RectangleF rect = Region;
            PointF point = new PointF(pointF.X,pointF.Y);
            switch (HandleType)
            {
                // 四条边中点的手柄
                case ShapeHandleType.Top:       // 上边中点：调整高度（Y方向）
                    rect.Y += point.Y;
                    rect.Height = rect.Height - point.Y;
                    break;
                case ShapeHandleType.Bottom:    // 下边中点：调整高度（Y方向）
                    rect.Height += point.Y;
                    break;
                case ShapeHandleType.Left:     // 左边中点：调整宽度（X方向）
                    rect.X += point.X;
                    rect.Width -= point.X;
                    break;
                case ShapeHandleType.Right:    // 右边中点：调整宽度（X方向）
                    rect.Width += point.X;
                    break;
                // 四条边角点的手柄
                case ShapeHandleType.TopLeft:   //左上角
                    rect.X += point.X;
                    rect.Y += point.Y;
                    rect.Width -= point.X;
                    rect.Height -= point.Y;
                    break;
                case ShapeHandleType.TopRight:  //右上角
                    rect.Y += point.Y;
                    rect.Width += point.X;
                    rect.Height -= point.Y;
                    break;
                case ShapeHandleType.BottomLeft:    //左下角
                    rect.X += point.X;
                    rect.Width -= point.X;
                    rect.Height += point.Y ;
                    break;
                case ShapeHandleType.BottomRight:   //右下角：调整宽高
                    rect.Width += point.X;
                    rect.Height += point.Y;
                    break;
               
            }
            if (rect.Width > 15 && rect.Height > 15)
            {
                Region = rect;
            }
            ExecuteResizeCallback();
        }
        public override void DrawShapeWithHandle(Graphics graphics)
        {
            //不感兴趣直接绘制
            if (!IsInterest)
            {
                //保留原来颜色
                Color tempBackColor = BackColor;
                BackColor = InterestColor;
                // 1、绘制外轮廓
                DrawBorder(graphics);
                // 2、计算填充路径区域（外部圆减去内部圆）
                DrawRegion(graphics);
                // 3、绘制手柄
                DrawHandles(graphics);
                // 4、绘制形状描述
                DrawDescription(graphics);
                // 5、绘制区域中心
                DrawRegionCenter(graphics);
                // 恢复颜色
                BackColor = tempBackColor;
                return;
            }
            if (IsSelected)
            {
                // 1、绘制填充区域
                DrawRegion(graphics);
                // 2、绘制形状手柄
                DrawHandles(graphics);
            }
            // 3、绘制区域边缘
            DrawBorder(graphics);
            // 4、绘制区域中心
            DrawRegionCenter(graphics);
            // 5、绘制形状描述
            DrawDescription(graphics);
        }
        public override void DrawHandle(Graphics graphics, float x, float y)
        {
            RectangleF handleRect = new RectangleF(x - HandleSize / 2, y - HandleSize / 2, HandleSize, HandleSize);
            using (var brush = new SolidBrush(Color.FromArgb(Alpha * 2, HandleColor)))
            {
                graphics.FillRectangle(brush, handleRect);
            }
            Pen pen = new Pen(HandleColor, BorderWidth);
            graphics.DrawRectangle(pen,Rectangle.Round(handleRect));
        }
        public override void DrawHandle(Graphics graphics, PointF point)
        {
        }
        public override ShapeHandleType GetHandleType(PointF point)
        {
            RectangleF rectangle = Region;
            // 计算中点坐标
            float midX = rectangle.Left + rectangle.Width / 2;
            float midY = rectangle.Top + rectangle.Height / 2;
            // 四个角的手柄
            if (IsInHandle(point, new PointF(rectangle.Left, rectangle.Top)))
                return ShapeHandleType.TopLeft;
            if (IsInHandle(point, new PointF(rectangle.Right, rectangle.Top)))
                return ShapeHandleType.TopRight;
            if (IsInHandle(point, new PointF(rectangle.Left, rectangle.Bottom)))
                return ShapeHandleType.BottomLeft;
            if (IsInHandle(point, new PointF(rectangle.Right, rectangle.Bottom)))
                return ShapeHandleType.BottomRight;
            // 四个边中点的手柄
            if (IsInHandle(point, new PointF(midX, rectangle.Top)))
                return ShapeHandleType.Top;
            if (IsInHandle(point, new PointF(rectangle.Right, midY)))
                return ShapeHandleType.Right;
            if (IsInHandle(point, new PointF(midX, rectangle.Bottom)))
                return ShapeHandleType.Bottom;
            if (IsInHandle(point, new PointF(rectangle.Left, midY)))
                return ShapeHandleType.Left;
            return ShapeHandleType.None;
        }
        public override Cursor GetSystemHandleType(PointF point)
        {
            switch (GetHandleType(point))
            {
                // 四个角方向的手柄
                case ShapeHandleType.TopLeft:
                case ShapeHandleType.BottomRight:
                    return Cursors.SizeNWSE;
                case ShapeHandleType.TopRight:
                case ShapeHandleType.BottomLeft:
                    return Cursors.SizeNESW;
                // 四个边中点的手柄
                case ShapeHandleType.Top:
                case ShapeHandleType.Bottom:
                    return Cursors.SizeNS; 
                case ShapeHandleType.Left:
                case ShapeHandleType.Right:
                    return Cursors.SizeWE; 
                default: return Cursors.SizeAll;
            }
        }
        public override bool IsInRegion(PointF point)
        {
            return (GetHandleType(point) != ShapeHandleType.None) 
                || _rectangleF.Contains(new Point((int)point.X, (int)point.Y));
        }
        public override bool IsInBackground(PointF point)
        {
            return _rectangleF.Contains(new Point((int)point.X, (int)point.Y)) 
                && !(GetHandleType(point) != ShapeHandleType.None);
        }
        public override bool IsInHandle(PointF inPoint, PointF point)
        {
            // 增大检测范围
            int detectionSize = HandleOutSize + 2;
            RectangleF handleRect = new RectangleF(  point.X - detectionSize / 2,  point.Y - detectionSize / 2, 
                detectionSize, detectionSize );
            return handleRect.Contains(inPoint);
        }
        public override bool IsInRotateHandle(PointF point)
        {
            return false;
        }
        #endregion

        #region 委托回调方法重写
        public override void ExecuteMoveCallback()
        {
            MoveEvents?.Invoke(this, Region.Location);
        }
        public override void ExecuteRotateCallback()
        {
            RotateEvents?.Invoke(this, Point);
        }
        public override void ExecuteResizeCallback()
        {
            ResizeEvents?.Invoke(this, Point);
        }
        public override void ExecuteAttachCallback()
        {
            AttachEvents?.Invoke(this, Point);
        }
        public override void ExecuteDetachCallback()
        {
            DetachEvents?.Invoke(this, Point);
        }
        public override void ExecuteSelectedCallback()
        {
            SelectedEvents?.Invoke(this, Point);
        }
        #endregion
    }
}
